package main

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"log"
	"os"
)

var (
	privateKey []byte
	publicKey  []byte
)

func readFile(keyFile string) ([]byte, error) {
	if f, err := os.Open(keyFile); err != nil {
		return nil, err
	} else {
		defer f.Close()
		content := make([]byte, 4096)
		if n, err := f.Read(content); err != nil {
			return nil, err
		} else {
			return content[:n], nil
		}
	}
}

func readKeyFile(privateKeyFile, publicKeyFile string) (err error) {
	if privateKey, err = readFile(privateKeyFile); err != nil {
		return
	}
	if publicKey, err = readFile(publicKeyFile); err != nil {
		return
	}
	return
}

//RSA数字签名
func RsaSignature(text string) ([]byte, error) {
	//解析pem格式私钥文件
	pemBlock, _ := pem.Decode(privateKey)
	priv, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes) //解析私钥
	if err != nil {
		return nil, err
	}
	message := []byte(text)

	rng := rand.Reader
	hashed := sha256.Sum256(message) //计算hash值

	//签名
	return rsa.SignPKCS1v15(rng, priv, crypto.SHA256, hashed[:])
}

//签名验证
func RsaVerify(text string, signature []byte) error {
	message := []byte(text)

	hashed := sha256.Sum256(message)     //计算hash值
	pemBlock, _ := pem.Decode(publicKey) //解析pem格式文件
	pubInterface, err := x509.ParsePKIXPublicKey(pemBlock.Bytes)
	if err != nil {
		return err
	}
	pub := pubInterface.(*rsa.PublicKey)

	err = rsa.VerifyPKCS1v15(pub, crypto.SHA256, hashed[:], signature)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error from verification: %s\n", err)
	}
	return err
}

func main() {
	err := readKeyFile("rsa_private_key.pem", "rsa_public_key.pem")
	if err != nil {
		log.Fatal(err)
	}
	plaintext := "因为我们没有什么不一样"
	signature, err := RsaSignature(plaintext)
	if err != nil {
		log.Fatalln(err)
	}
	fmt.Printf("Signature: %x\n", signature)

	err = RsaVerify(plaintext, signature)
	if err == nil {
		fmt.Println("Verify Pass")
	} else {
		fmt.Printf("Verify Failed: %s\n", err)

	}
}
